﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GGEditor.API.Editors;

namespace GGEditor.API.Samples.LandAndWater
{
	public partial class View : UserControl, IEditorView, IViewListener
	{
		private bool drawing = false;
		private IModelReader lawModel;

		public View()
		{
			InitializeComponent();

			SetStyle(ControlStyles.UserPaint |
			    ControlStyles.OptimizedDoubleBuffer |
			    ControlStyles.ResizeRedraw |
			    ControlStyles.DoubleBuffer, true);
		}

		protected float Dx
		{
			get
			{
				return Width / (float)lawModel.Width;
			}
		}

		protected float Dy
		{
			get
			{
				return Height / (float)lawModel.Height;
			}
		}

		protected override void OnPaintBackground(PaintEventArgs e)
		{
			// Even with double-buffering, do nothing here.
			// Avoid flicker by doing everything in OnPaint.
		}

		protected override void OnPaint(PaintEventArgs e)
		{
            Graphics g = e.Graphics;

			using (Brush bg = new SolidBrush(BackColor))
				g.FillRectangle(bg, ClientRectangle);

			if (lawModel == null)
				return;

			using (Brush fg = new SolidBrush(ForeColor))
			for (int y = 0; y < lawModel.Height; y++)
			{
				for (int x = 0; x < lawModel.Width; x++)
				{
					if (lawModel[x, y])
						g.FillRectangle(fg, x * Dx, y * Dy, Dx, Dy);
				}
			}

			for (int y = 0; y < lawModel.Height; y++)
				g.DrawLine(Pens.DarkBlue, 0, y * Dy, Width, y * Dy);

			for (int x = 0; x < lawModel.Width; x++)
				g.DrawLine(Pens.DarkBlue, x * Dx, 0, x * Dx, Height);
        }

        #region IEditorView Members

		public Control Control
		{
			get { return this; }
		}

		public void SubscribeTo(IEditorModel model)
		{
			model.ModelChanged += OnModelChanged;
		}

		public void UnsubscribeFrom(IEditorModel model)
		{
			model.ModelChanged -= OnModelChanged;
		}

		private void OnModelChanged(IEditorModel model)
		{
			lawModel = model as IModelReader;
			if (lawModel == null)
				throw new InvalidOperationException();

			Invalidate();
		}

		#endregion

		private void EditorView_MouseMove(object sender, MouseEventArgs e)
		{
			if (lawModel == null)
				return;

			if (drawing)
			{
				int x = (int)(e.X / Dx);
				int y = (int)(e.Y / Dy);

				GridSquareMouseDrag(x, y, e.Button == MouseButtons.Left);
			}
		}

		private void EditorView_MouseDown(object sender, MouseEventArgs e)
		{
			drawing = true;
			GridSquareMouseDown();
			EditorView_MouseMove(sender, e);
		}

		private void EditorView_MouseUp(object sender, MouseEventArgs e)
		{
			drawing = false;
			GridSquareMouseUp();
		}

		private void EditorView_MouseLeave(object sender, EventArgs e)
		{
			drawing = false;
		}

		#region Implementation of IViewListener

		public event GridSquareOperationEventHandler GridSquareMouseDown;
		public event GridSquareClickedEventHandler GridSquareMouseDrag;
		public event GridSquareOperationEventHandler GridSquareMouseUp;

		#endregion
	}

	public interface IViewListener
	{
		event GridSquareOperationEventHandler GridSquareMouseDown;
		event GridSquareClickedEventHandler GridSquareMouseDrag;
		event GridSquareOperationEventHandler GridSquareMouseUp;
		event KeyEventHandler KeyUp;
	}

	public delegate void GridSquareOperationEventHandler();
	public delegate void GridSquareClickedEventHandler(int x, int y, bool leftClick);
}
